package com.sunwayworld.baseline.framework.utils;

import com.hierynomus.msdtyp.AccessMask;
import com.hierynomus.msfscc.FileAttributes;
import com.hierynomus.msfscc.fileinformation.FileIdBothDirectoryInformation;
import com.hierynomus.mssmb2.SMB2CreateDisposition;
import com.hierynomus.mssmb2.SMB2CreateOptions;
import com.hierynomus.mssmb2.SMB2ShareAccess;
import com.hierynomus.smbj.SMBClient;
import com.hierynomus.smbj.auth.AuthenticationContext;
import com.hierynomus.smbj.connection.Connection;
import com.hierynomus.smbj.session.Session;
import com.hierynomus.smbj.share.DiskShare;
import com.sunwayworld.framework.exception.InvalidDataException;
import com.sunwayworld.framework.utils.FileUtils;
import com.sunwayworld.framework.utils.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.time.LocalDate;
import java.util.*;

public class SmbV23Utils {

    private static final Logger logger = LogManager.getLogger(SmbV23Utils.class);

    public static Session getSession(String ip, String username, String password){
        SMBClient client = null;
        Session session = null;
        Connection connection = null;
        AuthenticationContext authenticationContext = null;

        try {
            client = new SMBClient();
            connection = client.connect(ip);
            // 创建连接会话.
            authenticationContext = new AuthenticationContext(username, password.toCharArray(), null);
            session = connection.authenticate(authenticationContext);
        }catch (Exception e){
            logger.error(ExceptionUtils.getStackTrace(e));
            throw new InvalidDataException("SmbV23Utils getSession fail");
        }
        return session;
    }

    public static boolean connect(String ip, String username, String password){
        boolean result = true;
        SMBClient client = null;
        Session session = null;
        Connection connection = null;
        AuthenticationContext authenticationContext = null;

        try {
            client = new SMBClient();
            connection = client.connect(ip);
            // 创建连接会话.
            authenticationContext = new AuthenticationContext(username, password.toCharArray(), null);
            session = connection.authenticate(authenticationContext);
        }catch (Exception e){
            result = false;
        }finally {
            try {
                if (null != session) {
                    session.close();
                }
                if (null != client) {
                    client.close();
                }
            } catch (IOException ex) {
                logger.error(ex);
                result = false;
            }
        }
        return result;
    }

    public static List<Map<String, Object>> gainFileFromSmb(String filePath, String localPath, String ip, String username , String password){
        List<Map<String, Object>> fileMaps = new ArrayList<>();
        SMBClient client = null;
        Session session = null;
        Connection connection = null;
        AuthenticationContext authenticationContext = null;
        DiskShare diskShare = null;

        try {
            client = new SMBClient();
            connection = client.connect(ip);
            // 创建连接会话.
            authenticationContext = new AuthenticationContext(username, password.toCharArray(), null);
            session = connection.authenticate(authenticationContext);
            //操作共享文档
            diskShare = (DiskShare) session.connectShare(filePath);
            fileMaps = dealFileFromSmb(diskShare, filePath, localPath);
        }catch (Exception e){
            logger.error(ExceptionUtils.getStackTrace(e));
            throw new InvalidDataException("downloadFolder 获取共享文档文件失败");
        } finally {
            try {
                if (null != diskShare) {
                    diskShare.close();
                }
                if (null != session) {
                    session.close();
                }
                if (null != client) {
                    client.close();
                }
            } catch (IOException ex) {
                logger.error(ex);
            }
        }
        return fileMaps;
    }

    /**
     * 关闭数据库连接
     * @param client
     */
    public static void closeConnect(SMBClient client) {

    }

    private static List<Map<String, Object>> dealFileFromSmb(DiskShare diskShare, String filePath, String localPath) {
        LocalDate nowDate = LocalDate.now();
        List<Map<String, Object>> fileMaps = new ArrayList<>();
        String subStr = filePath.indexOf("\\")!=0? filePath:filePath.substring(1,filePath.length()); //共享文件夹名称

        try{
            List<FileIdBothDirectoryInformation> fileIdBothDirectoryInformationList = diskShare.list("","*");
            for (FileIdBothDirectoryInformation fileIdBothDirectoryInformation : fileIdBothDirectoryInformationList){
                String fileName = fileIdBothDirectoryInformation.getFileName();
                String beforeDateFile = nowDate.minusDays(1).toString();
                // SPEA测厚仪共享文件夹格式为：
                // 1./TestData/yyyy-MM-dd/TestData_yyyy-MM-dd.csv（厚度数据）
                // 2./TestData/yyyy-MM-dd/TestDataVIM_yyyy-MM-dd.csv（电压内阻数据）
                if (subStr.equals("TestData")) {
                    // 查询前一天的数据文件目录
                    if (fileName.contains(beforeDateFile)) {
                        List<FileIdBothDirectoryInformation> dataFileList = diskShare.list(beforeDateFile, "*");
                        for (FileIdBothDirectoryInformation dataFile : dataFileList) {
                            String dataFileName = dataFile.getFileName();
                            if (!StringUtils.equalsIgnoreCase(FileUtils.getFileExtension(dataFileName), "csv")) continue; //不是csv格式跳过
                            String sharePath = fileName+ "\\" + dataFileName; //共享文件夹位置：/TestData/yyyy-MM-dd/xxx.csv
                            if (sharePath.indexOf("\\") == 0) sharePath = sharePath.substring(1);
                            String saveUrl = localPath + "\\" + fileName + "\\" + dataFileName; // 保存位置：/files/instrumentAcq/“configId”/yyyy-MM-dd/xxx.csv
                            File file = getWriteFile(diskShare, sharePath, saveUrl);

                            Map<String, Object> fileMap = new HashMap<>();
                            if (dataFileName.contains("VIM")) {
                                fileMap.put("type", "SPEA2"); //电压内阻
                            } else {
                                fileMap.put("type", "SPEA1"); //测厚
                            }
                            fileMap.put("file", file);
                            fileMap.put("fileType", "CSV");
                            fileMaps.add(fileMap);
                            logger.info("获取文件到本地成功！！ 	sharePath:{} saveUrl:{}", sharePath, saveUrl);
                        }
                    }
                }
                // 英昊达测厚仪共享文件夹格式为：
                // 1./Data/A-yyyy-MM-dd(Workpiece).xls（厚度数据）
                else if (subStr.equals("Data")) {
                    // 查询前一天的数据文件
                    if (fileName.contains(beforeDateFile)) {
                        if (!StringUtils.equalsIgnoreCase(FileUtils.getFileExtension(fileName), "xls")) continue; //不是xls格式跳过
                        String sharePath = fileName; //共享文件夹位置：/Data/A-yyyy-MM-dd(Workpiece).xls
                        if (sharePath.indexOf("\\") == 0) sharePath = sharePath.substring(1,sharePath.length());
                        String saveUrl = localPath + "\\" + fileName; // 保存位置：/files/instrumentAcq/“configId”/A-yyyy-MM-dd(Workpiece).xls
                        File file = getWriteFile(diskShare, sharePath, saveUrl);

                        Map<String, Object> fileMap = new HashMap<>();
                        fileMap.put("type", "YHD"); //测厚
                        fileMap.put("fileType", "CSV"); //英昊达的文件格式可能被转过，只能以csv文本格式读取
                        fileMap.put("file", file);
                        fileMaps.add(fileMap);
                        logger.info("获取文件到本地成功！！ 	sharePath:{} saveUrl:{}", sharePath, saveUrl);
                    }
                }
                // 奥拓美电压内阻仪共享文件夹格式为：
                // 1./ATMBatterySys/detectiondb.mdb
                else if (subStr.equals("ATMBatterySys")) {
                    // 查询access数据库的db文件
                    if (fileName.indexOf("detectiondb") == 0) {
                        if (!StringUtils.equalsIgnoreCase(FileUtils.getFileExtension(fileName), "mdb")) continue; //不是mdb格式跳过
                        String sharePath = fileName; //共享文件夹位置：/ATMBatterySys/detectiondb.mdb
                        if (sharePath.indexOf("\\") == 0) sharePath = sharePath.substring(1,sharePath.length());
                        String saveUrl = localPath + "\\" + fileName; // 保存位置：/files/instrumentAcq/“configId”/detectiondb.mdb
                        File file = getWriteFile(diskShare, sharePath, saveUrl);

                        Map<String, Object> fileMap = new HashMap<>();
                        fileMap.put("type", "ATM"); //电压内阻
                        fileMap.put("fileType", "MDB");
                        fileMap.put("file", file);
                        fileMaps.add(fileMap);
                        logger.info("获取文件到本地成功！！ 	sharePath:{} saveUrl:{}", sharePath, saveUrl);
                    }
                }
            }
        }catch (Exception e){
            logger.error(ExceptionUtils.getStackTrace(e));
            throw new InvalidDataException("scanFolder 遍历“"+filePath+"”文件夹失败");
        }finally {

        }

        return fileMaps;
    }

    private static File getWriteFile(DiskShare diskShare, String sharePath, String saveUrl) {
        com.hierynomus.smbj.share.File shareFile = diskShare.openFile(sharePath, EnumSet.of(AccessMask.GENERIC_READ),
                EnumSet.of(FileAttributes.FILE_ATTRIBUTE_NORMAL), SMB2ShareAccess.ALL,
                SMB2CreateDisposition.FILE_OPEN_IF, EnumSet.noneOf(SMB2CreateOptions.class));
        File file = new File(saveUrl);
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        InputStream is = null;
        OutputStream os = null;
        try {
            is = shareFile.getInputStream();
            os = Files.newOutputStream(file.toPath());
            byte[] buffer = new byte[1024];
            while (is.read(buffer) != -1) {
                os.write(buffer);
                buffer = new byte[1024];
            }
        } catch (Exception e) {
            logger.error("获取文件到本地失败！！	sharePath:{} saveUrl:{}", sharePath, saveUrl);
        } finally {
            try {
                if (null != os) {
                    os.close();
                }
                if (null != is) {
                    is.close();
                }
            } catch (IOException ex) {
                logger.error(ex);
            }
        }
        return file;
    }

    /**
     * 将日期时间字符串自动补上0；2021-1-1 0:0->2021-01-01 00:00:00
     * @param str
     * @return
     */
    public static String fillDateStr(String str) {
        String[] dtStr = str.split(" ");
        //处理日期部分
        String date = dtStr[0];
        String[] dateStr = date.contains("-")?date.split("-"):date.split("/");
        String y = dateStr[0];
        String m = dateStr[1];
        if (m.length() == 1) m = "0" + m;
        String d = dateStr[2];
        if (d.length() == 1) d = "0" + d;
        //处理时间部分
        String time = dtStr[1];
        String[] timeStr = time.split(":");
        String h = timeStr[0];
        if (h.length() == 1) h = "0" + h;
        String mi = timeStr[1];
        if (mi.length() == 1) mi = "0" + mi;
        String s = timeStr.length<3?"00":timeStr[2];
        if (s.length() == 1) s = "0" + s;
        return y+"-"+m+"-"+d+" "+h+":"+mi+":"+s;
    }

    public static void main(String[] arg){
        String ip = "localhost";
        String username = "yuanx";
        String password = "yuanx";
        String url = "2022";
        String fileName = "12/11/20220501235015_1005_(39.144.4.155).txt";

//        File file = downloadFile(ip, username, password, url, fileName, "D://20120203");
//        storeFile(ip, username, password, url, "2022/pageoffice集成/pageoffice集成.docx",new File("D:\\pageoffice集成\\pageoffice集成\\pageoffice集成.docx"));
//        deleteFile(ip, username, password, url,"2022/pageoffice集成/pageoffice集成.docx");
    }
}
